package com.ebo.kline;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.ebo.kline.listener.CoupleChartGestureListener;

import com.ebo.kline.listener.MainInfoViewListener;
import com.ebo.kline.listener.SubInfoViewListener;
import com.ebo.kline.model.IKData;
import com.ebo.kline.render.ColorContentYAxisRenderer;
import com.ebo.kline.util.KLineXValueFormatter;
import com.ebo.kline.util.YValueFormatter;
import com.ebo.kline.view.ChartInfoView;
import com.ebo.kline.view.ChartInfoViewHandler;
import com.ebo.kline.view.LineChartXMarkerView;
import com.ebo.kline.view.LineChartYMarkerView;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.CandleData;
import com.github.mikephil.charting.data.CombinedData;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.ihongqiqu.util.DisplayUtils;
import com.wang.avi.AVLoadingIndicatorView;

import org.jetbrains.annotations.Nullable;

import java.util.List;


public class KLineView extends LinearLayout implements KDataAdapter.OnChartDataChangedListener {

    public static final int ELEMENT_NONE = -1;
    public static final int ELEMENT_TIME = 100;
    public static final int ELEMENT_K = 200;
    public static final int ELEMENT_SMA = 2001;
    public static final int ELEMENT_EMA = 2002;
    public static final int ELEMENT_BOLL = 2003;
    public static final int ELEMENT_VOL = 3001;
    public static final int ELEMENT_MACD = 3002;
    public static final int ELEMENT_KDJ = 3003;
    public static final int ELEMENT_RSI = 3004;
    public int XAXIS_LABEL_COUNT = 4;
    protected Context mContext;
    protected ChartInfoView mChartInfoView;
    private KDataAdapter mKDataAdapter;
    private KCombinedChart mChartMain;
    private KCombinedChart mChartSub;
    private CombinedData mChartMainData;
    private CombinedData mChartSubData;
    private int mCurrentMainChartMode = ELEMENT_TIME;
    private int mCurrentMainChartModeAssit = ELEMENT_NONE;
    private int mCurrentSubChartMode = ELEMENT_VOL;
    private int mCycle = 60;
    private TextView mHintView;

    private AVLoadingIndicatorView progressBar;
    private RelativeLayout mChartLayout;
    private TextView mDescMain,mDescSub;
    MainInfoViewListener mainListener;
    SubInfoViewListener subListener ;
    private boolean isNeedMove2Last = true;

    public static final int MAX_ENTRY = 40;


    public KLineView(Context context) {
        this(context, null);
    }

    public KLineView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public KLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        LayoutInflater.from(context).inflate(R.layout.view_kline, this);
        mChartMain = (KCombinedChart) findViewById(R.id.line_chart);
        mChartSub = (KCombinedChart) findViewById(R.id.bar_chart);
        mChartInfoView = (ChartInfoView) findViewById(R.id.k_info);
        progressBar = (AVLoadingIndicatorView) findViewById(R.id.progressBar);
        mChartLayout = findViewById(R.id.chart_layout);
        mDescMain = findViewById(R.id.tv_main_desc);
        mDescSub = findViewById(R.id.tv_sub_desc);
        mHintView = findViewById(R.id.chart_hint);
        mChartInfoView.setChart(mChartMain, mChartSub);
        mChartSub.setNoDataText(context.getString(R.string.loading));
        mChartMain.setNoDataText(context.getString(R.string.loading));

        ViewGroup.LayoutParams params = mChartInfoView.getLayoutParams();
        params.width = DisplayUtils.getScreenW((Activity) context)/3+50;
        mChartInfoView.setLayoutParams(params);

        mainListener = new MainInfoViewListener(mContext, Double.NaN, null, mChartInfoView,mDescMain, mChartSub);
        subListener =new SubInfoViewListener(mContext, Double.NaN, null, mChartInfoView, mDescSub,mChartMain);
        mainListener.setSubListener(subListener);
        mainListener.setConfig(KDataGenerator.mConfig);
        subListener.setSubListener(mainListener);
        subListener.setConfig(KDataGenerator.mConfig);
        mChartMain.setOnChartValueSelectedListener(mainListener);
        mChartSub.setOnChartValueSelectedListener(subListener);

        initMainChart();
        initSubChart();
        initChartListener();

        setChartBackgroundColor(Color.parseColor("#181b2a"));
        setBorderColor(Color.parseColor("#283852"));

    }

    public void setDataAdapter(KDataAdapter adapter) {
        this.mKDataAdapter = adapter;
        mainListener.setData(adapter.getData());
        subListener.setData(adapter.getData());
        this.mKDataAdapter.setListener(this);

        mChartMain.getXAxis().setAxisMaximum(adapter.getData().size()-0.5f);//(adapter.getData().size() - 0.5f);
        mChartSub.getXAxis().setAxisMaximum(adapter.getData().size()-0.5f);


        mChartMain.setVisibleXRangeMaximum(40);
        mChartSub.setVisibleXRangeMaximum(40);
        mChartMain.setVisibleXRangeMinimum(30);
        mChartSub.setVisibleXRangeMinimum(30);

        showMainChart(mCurrentMainChartMode);
        stopLoading();
    }

    boolean isShowSubView = true;

    //隐藏附图
    public void isShowSubView(int v) {
        mChartSub.setVisibility(v);
        //禁止手势
        mChartMain.setTouchEnabled(false);
        //去掉底部数字
        mChartMain.getXAxis().setTextColor(Color.TRANSPARENT);
        mChartMain.getXAxis().setTextSize(1);
    }

    //隐藏高亮（十字针线）
    public void isShowKInfo() {
        isShowSubView = false;
    }

    public void setBackground(int color) {
        mChartMain.setBackgroundColor(color);
    }

    public void stopLoading() {
//        progressBar.hide();
        mChartLayout.setVisibility(View.VISIBLE);
    }

    public void startLoading() {
        mChartLayout.setVisibility(View.GONE);
        progressBar.show();

    }

    public void setDataAdapter(KDataAdapter adapter, int cycle) {
        this.mCycle = cycle;
        setDataAdapter(adapter);

    }

    public void setChartBackgroundColor(int color) {
        mChartMain.setBackgroundColor(color);
        mChartSub.setBackgroundColor(color);
    }

    public void setBorderColor(int color) {
        mChartMain.setBorderColor(color);
        mChartSub.setBorderColor(color);
        mChartMain.getXAxis().setGridColor(color);
        mChartMain.getAxisLeft().setGridColor(color);
        mChartMain.getAxisRight().setGridColor(color);
        mChartSub.getXAxis().setGridColor(color);
        mChartSub.getAxisLeft().setGridColor(color);
        mChartSub.getAxisRight().setGridColor(color);
    }

    public void clearData() {
        progressBar.setVisibility(INVISIBLE);
        mHintView.setVisibility(VISIBLE);
    }

    private void showMainChart(int type) {
        if (mKDataAdapter == null) return;
        List<? extends IKData> list = mKDataAdapter.getData();
        mCurrentMainChartMode = type;
        switch (type) {
            case ELEMENT_TIME:
                this.mCycle = 60;
                mChartMainData.setData(mKDataAdapter.getmKDataGenerator().TimeData(list));
                mChartMainData.setData(new CandleData());
                mChartMainData.setHighlightEnabled(isShowSubView);
                mCurrentMainChartMode = ELEMENT_TIME;
                mCurrentMainChartModeAssit = ELEMENT_NONE;
                mCurrentSubChartMode = ELEMENT_VOL;
                break;
            case ELEMENT_K:
                mChartMainData.setData(mKDataAdapter.getmKDataGenerator().KData(list));
                mChartMainData.setData(mKDataAdapter.getmKDataGenerator().SMA(list));
                if (mCurrentMainChartModeAssit == ELEMENT_NONE)
                    mCurrentMainChartModeAssit = ELEMENT_NONE;


                break;
        }

        LineChartYMarkerView mvy = new LineChartYMarkerView(mContext,3);
        LineChartXMarkerView mvx = new LineChartXMarkerView(mContext, mKDataAdapter.getData());
        mvx.setChartView(mChartMain);
        mvy.setChartView(mChartMain);
        mChartMain.setMarker(mvy);
        mChartMain.setXMarker(mvx);
        mChartMain.getXAxis().setValueFormatter(new KLineXValueFormatter(mKDataAdapter.getData()));


        showMainChartAssit(mCurrentMainChartModeAssit);
        showSubChart(mCurrentSubChartMode);

        if(isNeedMove2Last){
            mChartMain.moveViewToX(mChartMainData.getEntryCount());
            mChartSub.moveViewToX(mChartSubData.getEntryCount());
            isNeedMove2Last = false;
        }
//
//
//        mChartMain.notifyDataSetChanged();
//        mChartMain.invalidate();
//        mChartMain.moveViewToX(mChartMainData.getEntryCount());

    }

    private void showMainChartAssit(int type) {

        List<? extends IKData> list = mKDataAdapter.getData();
        LineData lineData = mChartMainData.getLineData();
        mCurrentMainChartModeAssit = type;
        switch (type) {
            case ELEMENT_SMA:
                lineData = mKDataAdapter.getmKDataGenerator().SMA(list);
                break;
            case ELEMENT_EMA:
                lineData = mKDataAdapter.getmKDataGenerator().EMA(list);
                break;
            case ELEMENT_BOLL:
                lineData = mKDataAdapter.getmKDataGenerator().BOLL(list);
                break;
        }
        if (lineData != null) {
//            lineData.addDataSet(mKDataAdapter.getmKDataGenerator().PaddingData(list));
        }
        mChartMainData.setData(lineData);
        LineChartXMarkerView mvx = new LineChartXMarkerView(mContext, mKDataAdapter.getData());
        mvx.setChartView(mChartMain);
        mChartMain.setXMarker(mvx);
        mChartMain.getXAxis().setValueFormatter(new KLineXValueFormatter(mCycle, mKDataAdapter.getData()));
        mChartMain.notifyDataSetChanged();
        mChartMain.invalidate();

        if(list.size() > 0){
            mainListener.onOtherValueSelected(list.size()-1);
        }

    }







    private void showSubChart(int type) {

        List<? extends IKData> list = mKDataAdapter.getData();
        mCurrentSubChartMode = type;
        LineData lineData = mChartMainData.getLineData();
        switch (type) {
            case ELEMENT_VOL:
                lineData = new LineData();
                mChartSubData.setData(mKDataAdapter.getmKDataGenerator().VOLData(list));
                break;
            case ELEMENT_MACD:
                CombinedData cdata = mKDataAdapter.getmKDataGenerator().MACD(list);
                mChartSubData.setData(cdata.getBarData());
                lineData = cdata.getLineData();
                break;
            case ELEMENT_KDJ:
                lineData = mKDataAdapter.getmKDataGenerator().KDJData(list);
                mChartSubData.setData(new BarData());
                break;
            case ELEMENT_RSI:
                lineData = mKDataAdapter.getmKDataGenerator().RSIData(list);
                mChartSubData.setData(new BarData());
                break;
        }
        if (lineData != null) {
//            lineData.addDataSet(mKDataAdapter.getmKDataGenerator().PaddingData(list));
        }
        mChartSubData.setData(lineData);

        if (type == ELEMENT_MACD) {
            mChartSub.getAxisRight().resetAxisMinimum();
        } else {
            mChartSub.getAxisRight().setAxisMinimum(0);
        }

//        adjustElementsSize(mChartSub,10000);

        mChartSub.getXAxis().setValueFormatter(new KLineXValueFormatter(mKDataAdapter.getData()));
        setOffset();

        mChartSub.notifyDataSetChanged();
        mChartSub.invalidate();
        mChartSub.getAxisRight().resetAxisMaximum();

        if(list.size() > 0){
            subListener.onOtherValueSelected(list.size()-1);
        }

    }

    public void adjustElementsSize(KCombinedChart chart, float maximum ){
        chart.getAxisRight().setAxisMaximum(maximum);
        chart.getAxisLeft().setAxisMaximum(maximum);
    }

    public void moveToLast() {
        mChartMain.moveViewToX(mChartMainData.getEntryCount());
        mChartSub.moveViewToX(mChartSubData.getEntryCount());//移动到最右
    }

    public void setChartType(int type){
        mCurrentMainChartMode = type;
        isNeedMove2Last = true;
        mainListener.setType(type);
    }

    public void showChart(int type) {
        if (type < 1000) {
            showMainChart(type);
        } else if (type > 1000 && type < 3000) {
            showMainChartAssit(type);
        } else if (type > 3000) {
            showSubChart(type);
        }
    }

    /**
     * 初始化K线图主图
     */
    private void initMainChart() {
        mChartMain.setScaleEnabled(true);
        mChartMain.setDrawBorders(false);
        mChartMain.setBorderWidth(0);
        mChartMain.setDragEnabled(true);
        mChartMain.setScaleYEnabled(false);
        mChartMain.getDescription().setEnabled(false);

        mChartMain.getLegend().setEnabled(false);
        mChartMain.setAutoScaleMinMaxEnabled(true);
        mChartMain.setViewPortOffsets(1, 8, 1, 40);

        XAxis xAxis = mChartMain.getXAxis();
        xAxis.setLabelCount(XAXIS_LABEL_COUNT, true);
        xAxis.setDrawLabels(true);
        xAxis.setTextColor(Color.WHITE);
        xAxis.setDrawAxisLine(true);
        xAxis.setTextColor(Color.parseColor("#778caa"));
        xAxis.setDrawGridLines(true);
        xAxis.setAvoidFirstLastClipping(true);
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setAxisMinimum(-0.5f);
        xAxis.setYOffset(2);

        YAxis yLAxis = mChartMain.getAxisRight();
        yLAxis.setLabelCount(5, true);
        yLAxis.setDrawLabels(true);
        yLAxis.setDrawGridLines(false);
        yLAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
        yLAxis.setDrawAxisLine(false);
        yLAxis.setTextColor(Color.WHITE);
        yLAxis.setDrawAxisLine(false);
        yLAxis.setTextColor(Color.parseColor("#778caa"));
        yLAxis.setDrawGridLines(true);
        yLAxis.setValueFormatter(new YValueFormatter(2));
        yLAxis.setXOffset(4);
        Transformer leftYTransformer = mChartMain.getRendererRightYAxis().getTransformer();
        ColorContentYAxisRenderer leftColorContentYAxisRenderer = new ColorContentYAxisRenderer(mChartMain.getViewPortHandler(), mChartMain.getAxisRight(), leftYTransformer);
        leftColorContentYAxisRenderer.setLabelInContent(true);
        leftColorContentYAxisRenderer.setUseDefaultLabelXOffset(false);
        mChartMain.setRendererRightYAxis(leftColorContentYAxisRenderer);


        YAxis yRAxis = mChartMain.getAxisLeft();
        yRAxis.setDrawLabels(false);
        yRAxis.setDrawGridLines(false);
        yRAxis.setDrawAxisLine(false);
        yRAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);

        mChartMainData = new CombinedData();
        mChartMainData.setData(new CandleData());
        mChartMainData.setData(new LineData());
        mChartMain.setData(mChartMainData);

    }


    protected void initSubChart() {

        mChartSub.setScaleEnabled(true);
        mChartSub.setDrawBorders(false);
        mChartSub.setBorderWidth(0);
        mChartSub.setDragEnabled(true);
        mChartSub.setScaleYEnabled(false);
        mChartSub.getDescription().setEnabled(false);
        mChartSub.setAutoScaleMinMaxEnabled(true);
        mChartSub.setDragDecelerationEnabled(false);
        mChartSub.setHighlightPerDragEnabled(false);
        mChartSub.getLegend().setEnabled(false);
        mChartSub.setViewPortOffsets(1, 4, 1, 0);


        XAxis xAxis = mChartSub.getXAxis();
        xAxis.setLabelCount(XAXIS_LABEL_COUNT, true);
        xAxis.setDrawLabels(false);
        xAxis.setTextColor(Color.WHITE);
        xAxis.setDrawAxisLine(true);
        xAxis.setDrawGridLines(true);
        xAxis.setAvoidFirstLastClipping(false);
        xAxis.setPosition(XAxis.XAxisPosition.TOP_INSIDE);
        xAxis.setAxisMinimum(-0.5f);
        xAxis.setTextColor(Color.parseColor("#778caa"));

        YAxis yLAxis = mChartSub.getAxisRight();
        yLAxis.setLabelCount(1, true);
        yLAxis.setDrawLabels(true);
        yLAxis.setDrawGridLines(true);
        yLAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
        yLAxis.setDrawAxisLine(false);
        yLAxis.setTextColor(Color.WHITE);
        yLAxis.setDrawAxisLine(false);
        yLAxis.setDrawGridLines(true);
        yLAxis.setValueFormatter(new YValueFormatter(2));
        yLAxis.setXOffset(4);
        yLAxis.setTextColor(Color.parseColor("#778caa"));
        Transformer leftYTransformer = mChartSub.getRendererRightYAxis().getTransformer();
        ColorContentYAxisRenderer leftColorContentYAxisRenderer = new ColorContentYAxisRenderer(mChartSub.getViewPortHandler(), mChartSub.getAxisRight(), leftYTransformer);
        leftColorContentYAxisRenderer.setLabelInContent(true);
        leftColorContentYAxisRenderer.setUseDefaultLabelXOffset(false);
        leftColorContentYAxisRenderer.hideFirstLabel();
        mChartSub.setRendererRightYAxis(leftColorContentYAxisRenderer);


        YAxis yRAxis = mChartSub.getAxisLeft();

        yRAxis.setDrawLabels(false);
        yRAxis.setDrawGridLines(false);
        yRAxis.setDrawAxisLine(false);
        yRAxis.setAxisMinimum(0);


        mChartSubData = new CombinedData();
        mChartSubData.setData(new BarData());
        mChartSubData.setData(new LineData());
        mChartSub.setData(mChartSubData);
    }

    private void initChartListener() {
        mChartMain.setOnChartGestureListener(new CoupleChartGestureListener(mChartMain, mChartSub));
        mChartSub.setOnChartGestureListener(new CoupleChartGestureListener(mChartSub, mChartMain));

        mChartMain.setOnTouchListener(new ChartInfoViewHandler(mChartMain));
        mChartSub.setOnTouchListener(new ChartInfoViewHandler(mChartSub));

    }


    /**
     * align two chart
     */
    private void setOffset() {
        float lineLeft = mChartMain.getViewPortHandler().offsetLeft();
        float barLeft = mChartSub.getViewPortHandler().offsetLeft();
        float lineRight = mChartMain.getViewPortHandler().offsetRight();
        float barRight = mChartSub.getViewPortHandler().offsetRight();
        float offsetLeft, offsetRight;
        if (barLeft < lineLeft) {
            offsetLeft = Utils.convertPixelsToDp(lineLeft - barLeft);
            mChartSub.setExtraLeftOffset(offsetLeft);
        } else {
            offsetLeft = Utils.convertPixelsToDp(barLeft - lineLeft);
            mChartMain.setExtraLeftOffset(offsetLeft);
        }
        if (barRight < lineRight) {
            offsetRight = Utils.convertPixelsToDp(lineRight);
            mChartSub.setExtraRightOffset(offsetRight);
        } else {
            offsetRight = Utils.convertPixelsToDp(barRight);
            mChartMain.setExtraRightOffset(offsetRight);
        }

    }


    @Override
    public void onDataChanged() {

    }

    @Override
    public void onLastChanged(double lastPrice) {
        mainListener.setLastPrice(lastPrice);
        subListener.setLastPrice(lastPrice);
    }


    /**
     * according to the price to refresh the last data of the chart
     */
//    public void refreshData(float price) {
//        if (price <= 0 || price == mLastPrice) {
//            return;
//        }
//        mLastPrice = price;
//        CombinedData data = mChartMain.getData();
//        if (data == null) return;
//        LineData lineData = data.getLineData();
//        if (lineData != null) {
//            ILineDataSet set = lineData.getDataSetByIndex(0);
//            if (set.removeLast()) {
//                set.addEntry(new Entry(set.getEntryCount(), price));
//            }
//        }
//        CandleData candleData = data.getCandleData();
//        if (candleData != null) {
//            ICandleDataSet set = candleData.getDataSetByIndex(0);
//            if (set.removeLast()) {
//                IKData hisData = mKDataAdapter.getData().get(mKDataAdapter.getData().size() - 1);
//                hisData.setClose(price);
//                hisData.setHigh(Math.max(hisData.getHigh(), price));
//                hisData.setLow(Math.min(hisData.getLow(), price));
//                set.addEntry(new CandleEntry(set.getEntryCount(), (float) hisData.getHigh(), (float) hisData.getLow(), (float) hisData.getOpen(), (float) price));
//            }
//        }
//        mChartMain.notifyDataSetChanged();
//        mChartMain.invalidate();
//    }


}
